package com.tspoon.traceur;
import org.assertj.core.api.Assertions;
import org.junit.After;
import org.junit.Test;
import java.io.PrintWriter;
import java.io.StringWriter;
import io.reactivex.annotations.NonNull;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Predicate;
import static org.assertj.core.api.Assertions.assertThat;
public class TraceurTest {
@After
public void tearDown() {
Traceur.disableLogging();
}
@Test
public void callSiteIsShownInStackTrace() throws Exception {
// Assumption - Call site not shown when Traceur not enabled
try {
StreamFactory.createNullPointerExceptionObservable().blockingFirst();
} catch (Throwable t) {
final String exceptionAsString = exceptionAsString(t);
printStackTrace("Default Stacktrace", exceptionAsString);
assertThat(exceptionAsString).doesNotContain("StreamFactory");
}
// Enable Traceur and ensure call site is shown
Traceur.enableLogging();
try {
StreamFactory.createNullPointerExceptionObservable().blockingFirst();
Assertions.failBecauseExceptionWasNotThrown(Throwable.class);
} catch (Throwable t) {
final String exceptionAsString = exceptionAsString(t);
printStackTrace("Traceur Stacktrace", exceptionAsString);
assertThat(exceptionAsString).contains("StreamFactory");
}
}
@Test
public void filtersStackTraces() throws Exception {
// Assumption - Shims are not filtered when filtering is disabled
Traceur.enableLogging(new TraceurConfig(false));
try {
StreamFactory.createNullPointerExceptionObservable().blockingFirst();
Assertions.failBecauseExceptionWasNotThrown(Throwable.class);
} catch (Throwable t) {
final String exceptionAsString = exceptionAsString(t);
printStackTrace("Exception without filtering", exceptionAsString);
assertThat(exceptionAsString).contains("TraceurException.java");
assertThat(exceptionAsString).contains("ObservableOnAssembly.<init>");
}
// Enable filtering and ensure shims are filtered
Traceur.enableLogging(new TraceurConfig(true));
try {
StreamFactory.createNullPointerExceptionObservable().blockingFirst();
Assertions.failBecauseExceptionWasNotThrown(Throwable.class);
} catch (Throwable t) {
final String exceptionAsString = exceptionAsString(t);
printStackTrace("Exception with filtering", exceptionAsString);
assertThat(exceptionAsString).doesNotContain("TraceurException.java");
assertThat(exceptionAsString).doesNotContain("ObservableOnAssembly.<init>");
}
}
@Test
public void usingRetryDoesNotFail() {
Traceur.enableLogging();
StreamFactory.createNullPointerExceptionObservable()
.doOnError(new Consumer<Throwable>() {
@Override
public void accept(@NonNull Throwable throwable) throws Exception {
// Needed to trigger error scenario
}
})
.retry(1)
.test()
.assertError(new Predicate<Throwable>() {
@Override
public boolean test(@NonNull Throwable throwable) throws Exception {
return throwable instanceof NullPointerException
&& throwable.getCause() instanceof TraceurException;
}
});
}
private static void printStackTrace(String sectionName, String exceptionAsString) {
printSectionSeparator(sectionName);
System.out.println(exceptionAsString);
}
private static String exceptionAsString(Throwable t) {
final StringWriter sw = new StringWriter();
t.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
private static void printSectionSeparator(String sectionName) {
System.out.println("============== " + sectionName + " ==============");
}
}